package cn.baiweigang.uu.service.linearswap;

import cn.baiweigang.uu.api.linearswap.AccountApi;
import cn.baiweigang.uu.constants.BtcConfig;
import cn.baiweigang.uu.db.AccountInfoDb;
import cn.baiweigang.uu.enums.ContractCodeEnum;
import cn.baiweigang.uu.enums.MarginModeEnum;
import cn.baiweigang.uu.enums.PeriodEnum;
import cn.baiweigang.uu.enums.SymbolEnum;
import cn.baiweigang.uu.model.AccountInfo;
import cn.baiweigang.uu.model.DataMap;
import cn.baiweigang.uu.utils.LogUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;

@Service
public class AccountService {

    @Autowired
    private AccountApi accountApi;

    /**
     * 从HB服务端读取账户信息
     *
     * @param accountInfo
     */
    public void updateAccountFromHB(AccountInfo accountInfo) {
        accountApi.updateAccountInfoFromHB(accountInfo);
    }

    /**
     * 根据账号名 从DB读取账户信息
     *
     * @param accountName
     * @return
     */
    public AccountInfo queryFromDb(String accountName) {
        DataMap dataMap = AccountInfoDb.query(accountName);
        return convert2(dataMap);
    }

//    public List<AccountInfo> getAllAccount() {
//        List<AccountInfo> accountInfoList = new ArrayList<>();
//        //从DB读取
//        List<DataMap> dataMapList = AccountInfoDb.queryAllAvailable();
//        for (DataMap dataMap : dataMapList) {
//            AccountInfo accountInfo = convert2(dataMap);
//            accountInfoList.add(accountInfo);
//            BtcConfig.setApiKey(accountInfo.getAccountName(), dataMap.getStringValue("api_key"),
//                    dataMap.getStringValue("secret_key"));
//        }
//        return accountInfoList;
//    }

    private AccountInfo convert2(DataMap dataMap) {
        if (dataMap == null) return null;
        AccountInfo accountInfo = new AccountInfo();
        accountInfo.setAccountName(dataMap.getStringValue("account_name"));
        accountInfo.setSymbol(SymbolEnum.byCode(dataMap.getStringValue("symbol")));
        accountInfo.setContractCode(ContractCodeEnum.byCode(dataMap.getStringValue("contract_code")));
        accountInfo.setMarginMode(MarginModeEnum.byCode(dataMap.getStringValue("margin_mode")));
        accountInfo.setForcedCloseUsd(dataMap.getDoubleValue("forced_close_usd"));
        accountInfo.setOpenVolume(dataMap.getLongValue("min_volume"));
        accountInfo.setMaxVolume(dataMap.getLongValue("max_volume"));
        accountInfo.setContractSize(new BigDecimal(dataMap.getStringValue("contract_size")));
        accountInfo.setPriceTick(new BigDecimal(dataMap.getStringValue("price_tick")));
        accountInfo.setStrategyName(dataMap.getStringValue("strategy_name"));
        accountInfo.setAvailable("1".equals(dataMap.getStringValue("status")));
        accountInfo.setPeriod(PeriodEnum.valueOf(dataMap.getStringValue("period")));
        //把key加载到内存中
        BtcConfig.setApiKey(accountInfo.getAccountName(), dataMap.getStringValue("api_key"),
                dataMap.getStringValue("secret_key"));
        return accountInfo;
    }

    public boolean check(AccountInfo accountInfo) {
        //从DB加载账号信息
        AccountInfo tmp = queryFromDb(accountInfo.getAccountName());
        if (tmp == null || !tmp.isAvailable()) {
            LogUtil.logError("账号在DB配置为不可用 " + accountInfo.getAccountName());
            return false;
        }
        //从服务端获取最新账号信息
        updateAccountFromHB(accountInfo);
        //检查账户余额
        if (accountInfo.getMarginBalance().doubleValue() < 5) {
            LogUtil.logError("账号：" + accountInfo.getAccountName() +
                    " 可用余额不足 余额=" + accountInfo.getMarginBalance());
            return false;
        }
        //计算开仓合约张数 计算公式=账户余额/(允许的USD强平点数*1张合约对应USD值) 取整
        if (accountInfo.getForcedCloseUsd() > 0 && accountInfo.getContractSize() != BigDecimal.ZERO) {
            long volume = (long) (accountInfo.getMarginAvailable().doubleValue() /
                    (accountInfo.getForcedCloseUsd() * accountInfo.getContractSize().doubleValue()));
            //和允许的最大和约数取小
            if (volume > accountInfo.getMaxVolume()) volume = accountInfo.getMaxVolume();
            LogUtil.logInfo("本轮开仓合约数量= " + volume);
            //调试阶段，先只开1
            accountInfo.setOpenVolume(volume);
        }
        return true;
    }
}
